package com.itmuch.youran.controller.member;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.itmuch.core.constant.ConstantCode;
import com.itmuch.core.constant.ConstantRedis;
import com.itmuch.core.converter.AjaxResult;
import com.itmuch.youran.domain.member.entity.Member;
import com.itmuch.youran.domain.member.vo.AuthenticationResponse;
import com.itmuch.youran.domain.member.vo.MemberEmailLoginVo;
import com.itmuch.youran.domain.member.vo.MemberMobileLoginVo;
import com.itmuch.youran.security.SecurityUser;
import com.itmuch.youran.security.SecurityUserFactory;
import com.itmuch.youran.security.TokenUtils;
import com.itmuch.youran.service.member.MemberService;
import com.itmuch.youran.service.redis.RedisStringService;

/**
 * 认证controller
 * 
 * @author 周立
 */
@RestController
@RequestMapping("/auth")
public class AuthenticationController {

	private final static Logger LOGGER = Logger.getLogger(AuthenticationController.class);

	@Value("${youran.token.header}")
	private String tokenHeader;

	@Autowired
	private RedisStringService redisStringService;

	@Autowired
	private AuthenticationManager authenticationManager;

	@Autowired
	private TokenUtils tokenUtils;

	@Autowired
	private UserDetailsService userDetailsService;
	@Autowired
	private MemberService memberService;

	@PostMapping("/mobile")
	public AjaxResult<AuthenticationResponse> mobileLogin(@RequestBody MemberMobileLoginVo vo)
			throws AuthenticationException {

		String mobile = vo.getMobile();
		// 如果当前用户是使用的手机验证码登录，而不是密码登录
		String vcode = this.redisStringService.getByKey(ConstantRedis.LOGIN_MOBILE_PREFIX + mobile);
		if (StringUtils.isNotBlank(vcode)) {

			// 验证码匹配
			if (vcode.equals(vo.getVcode())) {
				Member member = this.memberService.loginByMobile(mobile);

				String token = this.tokenUtils.generateToken(SecurityUserFactory.create(member));

				// 颁发token
				return new AjaxResult<AuthenticationResponse>().success(new AuthenticationResponse(token));
			}
		}

		// 不匹配的情况
		return new AjaxResult<AuthenticationResponse>().error(ConstantCode.WRONG_VCODE);
	}

	@PostMapping("/email")
	public AjaxResult<AuthenticationResponse> emailLogin(@RequestBody MemberEmailLoginVo vo) {
		try {
			// Perform the authentication
			Authentication authentication = this.authenticationManager
					.authenticate(new UsernamePasswordAuthenticationToken(vo.getEmail(), vo.getPassword()));
			SecurityContextHolder.getContext().setAuthentication(authentication);

			// Reload password post-authentication so we can generate token
			UserDetails userDetails = this.userDetailsService.loadUserByUsername(vo.getEmail());
			String token = this.tokenUtils.generateToken(userDetails);

			// Return the token
			return new AjaxResult<AuthenticationResponse>().success(new AuthenticationResponse(token));
		} catch (AuthenticationException e) {
			LOGGER.debug("登录失败，异常发生", e);
			return new AjaxResult<AuthenticationResponse>().error(ConstantCode.PARAMTER_ERROR_CODE);
		}
	}

	@RequestMapping(value = "refresh", method = RequestMethod.GET)
	public ResponseEntity<?> authenticationRequest(HttpServletRequest request) {
		String token = request.getHeader(this.tokenHeader);
		String username = this.tokenUtils.getUsernameFromToken(token);
		SecurityUser user = (SecurityUser) this.userDetailsService.loadUserByUsername(username);
		if (this.tokenUtils.canTokenBeRefreshed(token, user.getPasswordLastResetTime())) {
			String refreshedToken = this.tokenUtils.refreshToken(token);
			return ResponseEntity.ok(new AuthenticationResponse(refreshedToken));
		} else {
			return ResponseEntity.badRequest().body(null);
		}
	}

}
